package com.moli.iov.down.remote.impl;

import com.moli.iov.down.command.disruptor.DisruptorProducer;
import com.moli.iov.down.command.mq.SendCache;
import com.moli.iov.down.enums.command.CommandEnum;
import com.moli.iov.down.enums.command.TerminalSettingEnum;
import com.moli.iov.down.model.dto.remoting.CommandDto;
import com.moli.iov.down.model.dto.req.VehicleParamDto;
import com.moli.iov.down.model.po.VehicleParam;
import com.moli.iov.down.remote.IVehicleParamRemoteService;
import com.moli.iov.down.service.IVehicleParamService;
import com.moli.iov.real.service.IRealService;
import com.moli.iov.rest.RestResponse;

import java.util.*;

import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;

/**
 * <p>
 * 参数业务
 * </p>
 *
 * @author zql
 * @since 2019/9/17 17:19
 */
@Slf4j
@Service(group = "${service.group}")
public class VehicleParamRemoteServiceImpl implements IVehicleParamRemoteService {

    @Autowired
    private IVehicleParamService vehicleParamService;

    @Reference(group = "${service.group}", check = false)
    private IRealService realService;

    @Autowired
    private SendCache sendCache;

    @Autowired
    private DisruptorProducer disruptorProducer;

    /**
     * 参数查询命令
     *
     * @param vins
     * @return
     */
    @Override
    public RestResponse sendQueryParameterCommand(List<String> vins) {

        // 返回数据库不存在vin
        List<String> nonExistentVins = getNonExistentVins(vins);

        // 添加新的vin
        saveBatchVehicleParam(nonExistentVins);

        // 返回在线的vin
        List<String> onlineVins = getOnlineVins(vins);

        if (onlineVins != null && !onlineVins.isEmpty()) {
            // 发送参数查询命令
            sendCommand(onlineVins);
        }

        return RestResponse.success();
    }

    /**
     * 获取数据库不存在vin
     *
     * @param vins
     * @return
     */
    @Override
    public List<String> getNonExistentVins(List<String> vins) {
        VehicleParamDto vehicleParamDto = new VehicleParamDto();
        vehicleParamDto.setVins(vins);
        List<VehicleParam> vehicleParams = vehicleParamService.listVehicleParam(vehicleParamDto);

        List<String> nonExistentVins = new ArrayList<>();
        vins.forEach(vin -> nonExistentVins.add(vin));

        vehicleParams.forEach(v -> nonExistentVins.remove(v.getVin()));

        return nonExistentVins;
    }

    @Override
    public Set<String> getSoftVersionList() {
        List<VehicleParam> list = vehicleParamService.list();
        Set<String> softVersion = new HashSet<>();
        if (list != null && list.size() > 0) {
            for (VehicleParam vehicleParam : list) {
                if (vehicleParam != null && !StringUtils.isEmpty(vehicleParam.getDeviceSoftVersion())) {
                    softVersion.add(vehicleParam.getDeviceSoftVersion());
                }
            }
        }
        return softVersion;
    }

    /**
     * 批量添加参数查询数据
     *
     * @param vins
     */
    private void saveBatchVehicleParam(List<String> vins) {
        List<VehicleParam> vehicleParams = new ArrayList<>();
        vins.forEach(vin -> {
            VehicleParam vp = new VehicleParam();
            vp.setVin(vin);
            vehicleParams.add(vp);
        });

        vehicleParamService.saveBatch(vehicleParams);
    }

    /**
     * 返回在线的vins
     *
     * @param vins
     * @return
     */
    @Override
    public List<String> getOnlineVins(List<String> vins) {
        List<String> onlineVins = new ArrayList<>();
        try {
            RestResponse<Map<String, Boolean>> restResponse = realService.isOnlineMap(vins);
            if (restResponse == null) {
                log.error("终端参数查询  调用车辆实时服务失败 restResponse为空 参数：{}", vins);
                return onlineVins;
            }

            if (!restResponse.isFlag() ||
                    restResponse.getData() == null ||
                    restResponse.getData().isEmpty()) {
                log.error("终端参数查询 调用车辆实时服务 返回失败 入参：{} 出参：{}", vins, restResponse);
                return onlineVins;
            }

            restResponse.getData().entrySet().forEach(entry -> {
                if (entry.getValue()) {
                    onlineVins.add(entry.getKey());
                }
            });
        } catch (Exception e) {
            log.error("终端参数查询 调用车辆实时服务异常", e);
        }

        if (onlineVins.isEmpty()) {
            log.info("{} 不在线", vins.toString());
        }
        return onlineVins;
    }

    /**
     * 发送 参数查询命令
     *
     * @param onlineVins
     */
    private void sendCommand(List<String> onlineVins) {
        disruptorProducer.onData(assembleCommandReqDto(onlineVins));
    }

    /**
     * 组装命令实体
     *
     * @param vins
     * @return
     */
    private List<CommandDto> assembleCommandReqDto(List<String> vins) {
        List<CommandDto> commandDtos = new ArrayList<>();
        vins.forEach(vin -> {
            CommandDto cd = new CommandDto();
            cd.setVin(vin);
            cd.setCommand(CommandEnum.TERMINAL_PARAMETER_QUERY.getFlag());
            cd.setParameterIds(TerminalSettingEnum.getAllFlag());
            cd.setCommandNo(sendCache.getSerialNumber(vin));
            cd.setIsRetry(false);
            commandDtos.add(cd);
        });

        return commandDtos;
    }

    /**
     * 获取设备参数
     *
     * @param vehicleParamDto
     * @return
     */
    @Override
    public RestResponse<VehicleParam> getVehicleParam(VehicleParamDto vehicleParamDto) {

        List<VehicleParam> vehicleParams = vehicleParamService.listVehicleParam(vehicleParamDto);
        if (vehicleParams == null || vehicleParams.isEmpty()) {
            return RestResponse.failure("设备不存在");
        }

        return RestResponse.success(vehicleParams.get(0));
    }

    /**
     * 查询单个参数
     *
     * @param vin
     * @return
     */
    @Override
    public VehicleParam getVehicleParamByVin(String vin) {
        return vehicleParamService.getVehicleParamByVin(vin);
    }
}
